package com.panfeng.xcloud.boss.provider.member.security.resource;

import com.panfeng.xcloud.boss.provider.member.security.SecurityConstants;
import com.panfeng.xcloud.boss.provider.member.security.password.PwdAuthenticationSecurityConfig;
import com.panfeng.xcloud.boss.provider.member.security.verifyCode.VerifyCodeAuthenticationSecurityConfig;
import com.panfeng.xcloud.common.security.utils.IgnoreUrlMatcher;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;
import org.springframework.security.web.access.AccessDeniedHandler;

import java.util.List;

/**
 * 资源服务器配置
 */
@Configuration
@EnableResourceServer
@Slf4j
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

	@Autowired
	@Qualifier("oAuth2WebSecurityExpressionHandler")
	private OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler;

	@Autowired
	private AccessDeniedHandler accessDeniedHandler;

	@Autowired
	private UserAuthExceptionEntryPoint userAuthExceptionEntryPoint;

	@Autowired
	private VerifyCodeAuthenticationSecurityConfig verifyCodeAuthenticationSecurityConfig;

	@Autowired
	private PwdAuthenticationSecurityConfig pwdAuthenticationSecurityConfig;

	@Override
	public void configure(HttpSecurity http) throws Exception {
		//允许使用iframe 嵌套，避免swagger-ui 不被加载的问题
		http.headers().frameOptions().disable();

		ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
				.authorizeRequests();

		List<String> ignoreUrls = IgnoreUrlMatcher.getIgnoreUrls();

		ignoreUrls.add(SecurityConstants.DEFAULT_PWD_LOGIN_URL);
		ignoreUrls.add(SecurityConstants.DEFAULT_VERIFYCODE_LOGIN_URL);
		ignoreUrls.add("/oauth/**");
		ignoreUrls.add("/druid/**");
		ignoreUrls.add("/actuator/**");
		ignoreUrls.add("/actuator");
		ignoreUrls.add("/swagger-ui.html");
		ignoreUrls.add("/swagger-resources/**");
		ignoreUrls.add("/v2/api-docs");

		int ignoreUrlSize = ignoreUrls.size();
		log.info(">>> 被排除的鉴权资源大小:{},资源详情:{}",ignoreUrlSize,ignoreUrls);
		ignoreUrls.forEach(url -> registry.antMatchers(url).permitAll());

		http.apply(verifyCodeAuthenticationSecurityConfig)
				.and()
				.apply(pwdAuthenticationSecurityConfig)
				.and()
				.headers().frameOptions().disable()
				.and()
				.exceptionHandling().accessDeniedHandler(accessDeniedHandler)
				.and()
				.csrf().disable();

		//拦截所有请求，并使用springsecurity 的认证表达式方式进行权限拦截
		registry
				.anyRequest()
				.access("@permissionService.hasPermission(authentication,request)");
	}

	@Override
	public void configure(ResourceServerSecurityConfigurer resources) {
		//配置表达式处理器
		resources.expressionHandler(oAuth2WebSecurityExpressionHandler);
		resources.authenticationEntryPoint(userAuthExceptionEntryPoint);
		resources.accessDeniedHandler(accessDeniedHandler);
	}

	@Bean(name = "oAuth2WebSecurityExpressionHandler")
	public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler(ApplicationContext applicationContext) {
		OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler();
		expressionHandler.setApplicationContext(applicationContext);
		return expressionHandler;
	}
}